package cn.gx.kevin.common.bootenv;

import cn.gx.kevin.common.ui.LanguageStore;
import com.github.yitter.contract.IdGeneratorOptions;
import com.github.yitter.idgen.YitIdHelper;
import cn.gx.kevin.common.utils.*;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.core.env.Environment;
import org.springframework.web.context.WebApplicationContext;

import java.util.*;

/**
 * @ClassName: SpringContextUtil
 * @Description: 存放spring上下文环境,当spring环境创建完成后，会触发onEnvFinished
 * @author kevin.huang
 * @date 2015-12-10 下午5:30:49
 */
public class SpringContextUtil implements ApplicationContextAware {

	private static ISpringContextListener springContextListener = null;

	public final static Logger logger = LoggerFactory.getLogger(SpringContextUtil.class);

	public static void setSpringContextListener(ISpringContextListener springContextListener) {
		SpringContextUtil.springContextListener = springContextListener;
	}

	private static WebApplicationContext webContext = null; // Spring-mvc应用上下文环境

	private static ApplicationContext applicationContext; // Spring应用上下文环境

	public static boolean needToSetWebContext = true;

	/*****
	 * 获取Spring-mvc应用上下文环境
	 * ******/
	public static WebApplicationContext getWebContext() {
		return webContext;
	}

	public static void setWebContext(WebApplicationContext webContext) {
		SpringContextUtil.webContext = webContext;
		needToSetWebContext = false;
	}

	/*****
	 * 获取Spring应用上下文环境
	 * ******/
	public static ApplicationContext getApplicationContext() {
		return applicationContext;
	}

	public static void onContextDestroyed(final IBeforeContextDestroyed beforeDestory) {
		if (springContextListener != null) {
			springContextListener.onBeforeEvnDestory();
		}
		if(beforeDestory != null){
			beforeDestory.destroyed();
		}
	}

	@Override
	public void setApplicationContext(ApplicationContext arg0) throws BeansException {
		SpringContextUtil.applicationContext = arg0;
		logger.info("the Spring ApplicationContext loaded ok,going to loadLangConfig ,initExcludeValidCfg.......");
		try{
			LanguageStore.loadLangConfig(null);
		}catch (Exception x){
			logger.error("",x);
		}
		try {
			SysConfigParams.initExcludeValidCfg();
		}catch (Throwable x){
			logger.error("",x);
		}
		if(springContextListener == null){
			Object listner = getBean("springContextListener");
			if(listner != null){
				springContextListener = (ISpringContextListener)listner;
			}
		}
		if (springContextListener != null) {
			try {
				springContextListener.onEnvFinished();
			} catch (Exception ex) {
				logger.error("onSpringContextLoaded onEnvFinished call:{}", ex);
			}
		}
	}

	/**
	 * 获取对象
	 *
	 * @param name
	 * @return Object
	 * @throws BeansException
	 */
	public static Object getBean(String name) throws BeansException {
		Object obj = null;
		try {
			if (webContext != null) {
				obj = webContext.getBean(name);
			}else {
				obj = applicationContext.getBean(name);
			}
		} catch (Exception ex) {
			logger.warn("try1 the Spring ApplicationContext Cannot Fined the bean [" + name + "]");
		}
		return obj;
	}

	/**
	 * 获取当前环境
	 */
	public static Environment getEnvironment() {
		ApplicationContext ctx = getApplicationContext();
		if(ctx == null){
			logger.info("ApplicationContext is NUll !!!!!!! ");
		}
		return ctx.getEnvironment();
	}


	public static<T> T registerBean(String name, Class<T> clazz, Object... args) {
		BeanDefinitionBuilder beanDefinitionBuilder = BeanDefinitionBuilder.genericBeanDefinition(clazz);
		if (args.length > 0) {
			for (Object arg : args) {
				beanDefinitionBuilder.addConstructorArgValue(arg);
			}
		}
		BeanDefinition beanDefinition = beanDefinitionBuilder.getRawBeanDefinition();
		BeanDefinitionRegistry beanFactory = (BeanDefinitionRegistry)applicationContext.getAutowireCapableBeanFactory();
		beanFactory.registerBeanDefinition(name, beanDefinition);
		return applicationContext.getBean(name, clazz);
	}


}
